package com.microDynamic.utils;

import com.microDynamic.service.biz.FolderSettings;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * &Desc 文件工具类
 */
public class FileUtil {
    private static Logger logger = LoggerFactory.getLogger(FileUtil.class);

    /***
     * &Desc: xMind文件转换为zip文件
     * @param xMindFile xMind文件
     * @return java.io.File
     */
    public static File transferXMind2Zip(File xMindFile) {
        String urlPath = new FolderSettings().getUrlPath();
        String extractPath = "Extract" + urlPath;
        File extractDir = new File(extractPath);
        if (!extractDir.exists()) {
            extractDir.mkdirs(); // 确保Extract目录存在
        }
        // 复制xMind文件到Extract目录下，保持原扩展名（这里假设只是为了备份，而不是转换）
        File backupFile = new File(extractDir, xMindFile.getName());
        FileUtil.copyFileUsingApacheCommonsIO(xMindFile, backupFile);
        logger.info("xMind文件备份到:" + backupFile.getAbsolutePath());
        // 构建ZIP文件的绝对路径 + extractPath
        String zipFileDest =new FolderSettings().getUploadFolder();
        logger.info("zipFileDest路径为："+zipFileDest);
        String zipFileName = xMindFile.getName().replace(FileExtension.XMIND, FileExtension.ZIP);
        logger.info("zipFileName路径为："+zipFileName);
        File zipFile = new File(zipFileDest, zipFileName);
        logger.info("zipFile路径为："+zipFile.getAbsolutePath());
        // 如果ZIP文件已存在并且是目录，则删除它
        if (zipFile.exists() && zipFile.isDirectory()) {
            deleteDirectory(zipFile); // 需要实现此方法以递归删除目录
        }
        // 重命名文件（注意：这不是真正的转换，只是重命名！）
        Path source = backupFile.toPath();
        Path target = zipFile.toPath();
        try {
            Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);

        } catch (IOException e) {
            e.printStackTrace();
            logger.error("无法重命名文件为ZIP格式");
        }
        return target.toFile();
    }
    // 递归删除目录的方法（注意：这是一个简单示例，可能需要更健壮的错误处理）
    private static void deleteDirectory(File dir) {
        if (dir.isDirectory()) {
            for (File file : dir.listFiles()) {
                if (file.isDirectory()) {
                    deleteDirectory(file);
                } else {
                    file.delete();
                }
            }
        }
        dir.delete();
    }

    /***
     * &Desc: 解压文件到指定目录
     * @param zipPath 解压文件路径
     * @param descDir 解压到指定目录
     * @return void
     */
    public static void unZipFiles(String zipPath, String descDir) throws IOException {
        File zipFile = new File(zipPath);
        File pathFile = new File(descDir);
        logger.info("zipFile是否为文件夹:" + zipFile.isDirectory());
        logger.info("pathFile是否为文件夹:" + pathFile.isDirectory());
        logger.info("zip文件绝对路径为:" + zipFile);
        logger.info("pathFile文件绝对路径为:" + pathFile);
        logger.info("******************开始解压********************");

        // 检查解压目录是否存在
        if(pathFile.exists()){
            deleteDir(pathFile);
        }
        pathFile.mkdirs();

        // 解决zip文件中有中文目录或者中文文件
        ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));
        for (Enumeration entries = zip.entries(); entries.hasMoreElements();) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            String zipEntryName = entry.getName();
            InputStream in = zip.getInputStream(entry);
            String outPath = (descDir + "/" + zipEntryName);
            logger.info("entry文件是否为文件夹:" + entry.isDirectory());
            logger.info("outPath绝对路径为:" + outPath);

            // 判断路径是否存在,不存在则创建文件路径
            File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
            logger.info("outPath文件绝对路径为:" + file.getParent());
            if (!file.exists()) {
                file.mkdirs();
            }

            // 判断文件全路径是否为文件夹,如果是, 则不需要解压
            if (new File(outPath).isDirectory()) {
                continue;
            }

            // 执行解压
            OutputStream out = new FileOutputStream(outPath);
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            logger.info("out输出为:" + out.toString());
            // 关闭文件流
            in.close();
            out.close();
        }
        zip.close();
        logger.info("******************解压完毕********************");
    }

    /***
     * &Desc: 文件复制
     * @param source 源文件
     * @param dest 目标文件
     * @return void
     */
    private static void copyFileUsingApacheCommonsIO(File source, File dest) {
        try {
            FileUtils.copyFile(source, dest);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /***
     * &Desc: 删除带文件的目录
     * @param dir 目录
     * @return boolean
     */
    public static boolean deleteDir(File dir) {
        //先删除目录下的所有文件
        if (dir.isDirectory()) {
            String[] children = dir.list();
            //递归删除目录中的子目录下
            for (int item=0; item<children.length; item++) {
                boolean success = deleteDir(new File(dir, children[item]));
                if (!success) {
                    System.out.println("递归删除文件失败："+ new File(dir, children[item]).getAbsolutePath() );
                    return false;
                }
            }
        }
        // 目录此时为空，可以删除
        return dir.delete();
    }
}